package com.twq.conversionsparam

import java.util
import java.util.{Collections, Comparator}

import com.twq.rules.rule2.People

/**
 * Created by tangweiqun on 2017/11/18.
 */
object ImplicitView {
  def main(args: Array[String]): Unit = {
    //1、如果表达式不符合编译器要求的类型，编译器会查找能使之符合类型要求的隐式转换
    implicit def intToString(x: Int) = x.toString

    foo(2)

    val list = new util.ArrayList[String]()
    list.add("this")
    list.add("is")
    list.add("a")
    list.add("example")

    Collections.max(list)

    Collections.max(list, new Comparator[String] {
      override def compare(o1: String, o2: String): Int = o1.length - o2.length
    })

    implicit def funcToComparator(func: (String, String) => Int) = new Comparator[String] {
      override def compare(o1: String, o2: String): Int = func(o1, o2)
    }

    Collections.max(list, (o1: String, o2: String) => o1.length - o2.length)

    //2、如果T类型中没有成员e，但是我们还是想通过T.e来访问e，
    // 那么编译器会查找能应用到T类型并且返回类型包含成员e的隐式转换
    implicit class IntWithTimes(x: Int) {
      def times[A](f: => A): Unit = {
        def loop(current: Int): Unit =
          if (current > 0) {
            f
            loop(current - 1)
          }

        loop(x)
      }
    }

    5 times (println("Hi"))
  }

  def foo(msg: String) = println(msg)

  //2. 在构造参数中只能有一个非隐式参数.
  implicit class RichDate(date: java.util.Date) // OK!
  //implicit class Indexer[T](collecton: Seq[T], index: Int) // BAD!
  implicit class Indexer[T](collecton: Seq[T])(implicit people: People) // OK!


  //3. 隐式类的名字不能和相同作用域中的object，或者成员名字相同
  object Bar

  //implicit class Bar(x: Int) // BAD!
  val x = 5
  //implicit class x(y: Int) // BAD!
  //implicit不能用在case class上
  //implicit case class Baz(x: Int) // BAD!
}

//1. 必须定义在其他的 trait/class/object 中.
class Helpers {

  implicit class RichInt(x: Int) // OK!
}

//implicit class RichDouble(x: Double) // BAD!
